const Main = imports.ui.main;
/* This class represents a single display item containing information about a document.
+ * We take the current number of seconds in the constructor to avoid looking up the current
+ * time for every item when they are created in a batch.
*
* docInfo - DocInfo object containing information about the document
* currentSeconds - current number of seconds since the epoch
_init : function(docInfo, currentSecs, availableWidth) {
GenericDisplay.GenericDisplayItem.prototype._init.call(this, availableWidth);
this._docInfo = docInfo;
-
+
this._setItemInfo(docInfo.name, "");
- // We take the current number of seconds here to avoid looking up the current
- // time for every item
+
+ this._timeoutTime = -1;
this._resetTimeDisplay(currentSecs);
},
//// Public methods ////
- getUpdateTimeout: function() {
- return this._timeout;
+ getUpdateTimeoutTime: function() {
+ return this._timeoutTime;
},
// Update any relative-time based displays for this item.
//// Private Methods ////
+ // Updates the last visited time displayed in the description text for the item.
_resetTimeDisplay: function(currentSecs) {
let lastSecs = this._docInfo.lastVisited().getTime() / 1000;
let timeDelta = currentSecs - lastSecs;
let [text, nextUpdate] = Shell.Global.get().format_time_relative_pretty(timeDelta);
- this._timeout = nextUpdate;
+ this._timeoutTime = currentSecs + nextUpdate;
this._setDescriptionText(text);
}
};
GenericDisplay.GenericDisplay.prototype._init.call(this, width);
let me = this;
- this._updateTimeoutTarget = -1;
+ // We keep a single timeout callback for updating last visited times
+ // for all the items in the display. This avoids creating individual
+ // callbacks for each item in the display. So proper time updates
+ // for individual items and item details depend on the item being
+ // associated with one of the displays.
+ this._updateTimeoutTargetTime = -1;
this._updateTimeoutId = 0;
this._docManager = DocInfo.getDocManager(GenericDisplay.ITEM_DISPLAY_ICON_SIZE);
// Creates a DocDisplayItem based on itemInfo, which is expected to be a DocInfo object.
_createDisplayItem: function(itemInfo, width) {
let currentSecs = new Date().getTime() / 1000;
- let doc = new DocDisplayItem(itemInfo, currentSecs, width);
- let timeout = Math.round(doc.getUpdateTimeout() / 8)+1;
- if (this._updateTimeoutTarget < 0 || timeout < this._updateTimeoutTarget) {
- if (this._updateTimeoutId > 0)
- Mainloop.source_remove(this._updateTimeoutId);
- this._updateTimeoutId = Mainloop.timeout_add_seconds(timeout, Lang.bind(this, this._docTimeout));
- this._updateTimeoutTarget = doc.getUpdateTimeout();
- }
- return doc;
+ let docDisplayItem = new DocDisplayItem(itemInfo, currentSecs, width);
+ this._updateTimeoutCallback(docDisplayItem, currentSecs);
+ return docDisplayItem;
},
//// Private Methods ////
+
+ // A callback function that redisplays the items, updating their descriptions,
+ // and sets up a new timeout callback.
_docTimeout: function () {
let currentSecs = new Date().getTime() / 1000;
+ this._updateTimeoutId = 0;
+ this._updateTimeoutTargetTime = -1;
for (let docId in this._displayedItems) {
- let disp = this._displayedItems[docId];
- disp.redisplay(currentSecs);
+ let docDisplayItem = this._displayedItems[docId];
+ docDisplayItem.redisplay(currentSecs);
+ this._updateTimeoutCallback(docDisplayItem, currentSecs);
}
return true;
+ },
+
+ // Updates the timeout callback if the timeout time for the docDisplayItem
+ // is earlier than the target time for the current timeout callback.
+ _updateTimeoutCallback: function (docDisplayItem, currentSecs) {
+ let timeoutTime = docDisplayItem.getUpdateTimeoutTime();
+ if (this._updateTimeoutTargetTime < 0 || timeoutTime < this._updateTimeoutTargetTime) {
+ if (this._updateTimeoutId > 0)
+ Mainloop.source_remove(this._updateTimeoutId);
+ this._updateTimeoutId = Mainloop.timeout_add_seconds(timeoutTime - currentSecs, Lang.bind(this, this._docTimeout));
+ this._updateTimeoutTargetTime = timeoutTime;
+ }
}
};
this._icon = null;
this._previewIcon = null;
+ // An array of details description actors that we create over time for the item.
+ // It is used for updating the description text inside the details actor when
+ // the description text for the item is updated.
+ this._detailsDescriptions = [];
+
this.dragActor = null;
},
text: this._description.text });
textDetails.append(detailsDescription, Big.BoxPackFlags.NONE);
+ this._detailsDescriptions.push(detailsDescription);
+
mainDetails.append(textDetails, Big.BoxPackFlags.EXPAND);
this._ensurePreviewIconCreated();
this.actor.add_actor(this._description);
},
+ // Sets the description text for the item, including the description text
+ // in the details actors that have been created for the item.
_setDescriptionText: function(text) {
this._description.text = text;
+ for (let i = 0; i < this._detailsDescriptions.length; i++) {
+ let detailsDescription = this._detailsDescriptions[i];
+ if (detailsDescription != null) {
+ detailsDescription.text = text;
+ }
+ }
},
//// Virtual protected methods ////
*
* Format a time value for human consumption only. The passed time
* value is a delta in terms of seconds from the current time.
+ * This function needs to be in C because of its use of ngettext() which
+ * is not accessible from JavaScript.
*/
void
shell_global_format_time_relative_pretty (ShellGlobal *global,
*next_update = MINUTE - delta;
} else if (delta < HOUR) {
*text = g_strdup_printf (ngettext ("%d minute ago", "%d minutes ago", delta / MINUTE), delta / MINUTE);
- *next_update = MINUTE*(delta-MINUTE + 1) - delta;
+ *next_update = MINUTE - (delta % MINUTE);
} else if (delta < DAY) {
*text = g_strdup_printf (ngettext ("%d hour ago", "%d hours ago", delta / HOUR), delta / HOUR);
- *next_update = HOUR*(delta-HOUR + 1) - delta;
+ *next_update = HOUR - (delta % HOUR);
} else if (delta < WEEK) {
*text = g_strdup_printf (ngettext ("%d day ago", "%d days ago", delta / DAY), delta / DAY);
- *next_update = DAY*(delta-DAY + 1) - delta;
+ *next_update = DAY - (delta % DAY);
} else {
*text = g_strdup_printf (ngettext ("%d week ago", "%d weeks ago", delta / WEEK), delta / WEEK);
- *next_update = WEEK*(delta-WEEK + 1) - delta;
+ *next_update = WEEK - (delta % WEEK);
}
}